热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

可能会|都会_使用React和Next.js构建博客

篇首语:本文由编程笔记#小编为大家整理,主要介绍了使用React和Next.js构建博客相关的知识,希望对你有一定的参考价值。

篇首语:本文由编程笔记#小编为大家整理,主要介绍了使用 React 和 Next.js 构建博客相关的知识,希望对你有一定的参考价值。




Next.js 是由 Vercel 创建和维护的基于 React 的应用程序框架。本教程将从零开始学习如何使用 Next.js 构建一个小型的博客网站:



  • 基本页面创建

  • Markdown 文件生成的动态路由

  • 静态生成(在构建时渲染)

  • 服务器端渲染(在请求时渲染)

文章涉及的代码仓库地址:https://github.com/QuintionTang/react-blog


Next.js 适合博客吗?

本教程将通过创建一个简单的博客来展示 Next.js 功能,那么 Next.js 适合这样的博客的开发吗?先来了解一下一般博客都需要什么?



  • WordPress 是一个内容管理系统 (CMS),它为三分之一的网站提供支持,通过在每次请求时将可编辑的数据库内容渲染到 php 模板中来为页面提供服务。它非常适合定期更新的内容,但性能、安全性和数据备份需要一定的自定义设置。



  • 静态站点生成器 (SSG),例如 Eleventy 或 Gatsby 创建预渲染文件,无需服务器端或数据库即可快速构建静态站点,在版本控制、性能和安全性都非常出色,但构建步骤和以开发人员为中心的过程可能会减慢发布速度,尤其是在大型网站上。

Next.js 是一个基于 React 的应用程序框架,它几乎没有特定于博客功能。但是,它可以提供了一种实现机制:



  1. 在可能的情况下,Next.js 生成静态内容,如 SSG,这些页面加载速度非常快,可以被搜索引擎快速收录,并且可以在任何有或没有 Javascript 的设备上阅读。

  2. 在第一次加载后,Next.js 应用程序的行为类似于单页应用程序 (SPA),后续页面和代码会以渐进式下载,无需刷新整页。

  3. Next.js 为每个请求提供服务器端渲染 (SSR),为个人用户提供实时 CMS 更新或自定义内容变得更加容易。

如果网站可能会从基本博客迭代为更复杂的网站,例如在线商店、新闻聚合服务、社交媒体平台等,可以考虑使用 Next.js


开始

本教程正在构建的内容,可以在 GitHub 上找到完整的代码。可以通过在终端中输入以下命令,在 WindowsmacOSLinux 上下载、安装和启动它:

git clone git@github.com:QuintionTang/react-blog.git
cd react-blog
npm i
npm run dev

然后在浏览器中输入 localhost:3000 打开主页。


从头开始构建

Next.js 提供了一个 create-next-app 工具来快速开始使用应用程序模板。本教程将展示如何从头开始构建站点:如添加静态资源或者页面。


安装 Next.js 和 React

与其他 Node.js 或者 VUE 项目一样,首先创建一个目录并初始化 package.json 文件:

mkdir react-blog
cd react-blog
npm init

然后安装 Next.jsReact 作为依赖项:

npm install next react react-dom --save

添加开发构建脚本设置,如下所示,在 package.json 文件的 scripts 属性中添加:

"scripts":
"dev": "next dev",
"build": "next build",
"start": "next start"

创建第一个页面

Next.js 有一个基于文件系统的路由器。在项目的 pages 目录中创建的任何 React 组件文件都会自动呈现为一个页面。

要创建一个页面,需要在 pages 目录中添加一个 index.js 文件。将以下代码添加到 ./pages/index.js 文件中,返回 JSX 代码的功能性 React 组件:

export default function Home()
return (
<>
Next.js 博客网站


这个博客网站将使用 Next.js



);

要启动 Next.js 开发服务器,从项目根目录在终端中运行 npm run dev(可以使用 npx next dev),然后在浏览器中打开 http://localhost:3000/

Next.js 已经确定页面可以预渲染,所以它在开发模式下显示一个闪电图标

可以在自动路由的页面目录中创建类似的文件,如下:



  • pages/index.js 用于呈现博客主要

  • pages/about.js 呈现一个 /about 页面


增加链接

在 JSX 代码中使用标准 html 标签创建指向另一个页面的超链接。如果该页面位于同一个 Next.js 站点内,浏览器将会刷新整个页面。可以使用 next/link 中的 组件实现页面跳转。在根页面 /index.js 上创建指向 /about 页面的链接,代码如下:

import Link from "next/link";
export default function Home()
return (
<>
Next.js 博客网站


这个博客网站将使用
Next.js



更多内容请点击" "

关于我们...



);

当点击 关于我们... 链接时,Next.js 将使用 Ajax 请求下载 /about 的内容一次并缓存,然后再页面中呈现。


增加 元素

可以使用 next/head 中的 组件来更改页面标题和元标记,如下:

import Head from "next/head";
import Link from "next/link";
export default function Home()
return (
<>


name="description"
cOntent="这是一个由 Next.js 驱动的网站"
/>

Next.js 博客网站


这个博客网站将使用 Next.js



更多内容请点击" "

关于我们...



);

点击浏览器查看源代码,可以看到相关 HTML 标签。


增加静态资源

public 目录用于存放静态资源,如图标、robots.txt 或其它更新频率低的文件。可以增加自己的文件或从初始项目存储库复制 favicon.ico 和图像子目录。


创建模板

Next.js 使用 React 组件来实现模板化,接下来项目根目录下创建一个新的 components 文件夹,然后添加 layout.js 来定义一个新的 组件:

import Header from "./header";
import Footer from "./footer";
export default function Layout( children, title )
return (
<>

children



);

任何使用此组件的页面都会传递一个 props 对象,该对象包含作为子值 children 的内容。 还将引用了另外两个组件,分别是 component/header.js 中的 ,主要呈现一个 ,包含主页链接、内联 SVG Logo和 默认为 /images/header.jpg 的图像:

import Link from "next/link";
export default function Header( title )
const headerImg = "/images/" + (title || "header.jpg");
return (




xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"

>


Next.js 博客




src=headerImg

/>


);

第二个组件是 component/footer.js 中的

,呈现
内容,其中包含指向 GitHub 存储库和内联 SVG 的链接:

export default function Footer()
return (


);

接下来更新 pages/index.js ,将使用自定义的 组件:

import Layout from "../components/layout";
import Head from "next/head";
import Link from "next/link";
export default function Home()
return (



name="description"
cOntent="这是一个由 Next.js 驱动的网站"
/>

Next.js 博客网站


这个博客网站将使用 Next.js



更多内容请点击" "

关于我们...



);

然后对 pages/about.js 和创建的任何其他页面执行相同操作。

import Layout from "../components/layout";
import Head from "next/head";
export default function Home()
return (




关于我们


DevPoint 是 WEB
开发的分享中心,用自己的热情来分享互联网的点滴,以此激励自己加强学习提升自我。



);

更新后的效果如下:


使用动态路由查看博客内容

使用 JSX 创建内容并不是特别实用,尤其是对于常规博客文章,对于开发者比较喜欢 Markdown 的方式写博客。Next.js 可以使用任何来源创建页面。这些可以在构建时静态生成,并使用动态路由将数据映射到 URL。

在继续之前,先来创建一个文章目录,用于存放博客的 Markdown 文件。例如:articles/article-01.md

---
title: 使用 React 和 Next.js 构建博客
description: Next.js 是由 Vercel 创建和维护的基于 React 的应用程序框架。本教程将从零开始学习如何使用 Next.js 构建一个小型的博客网站。
date: 2022-01-22
tags:
- HTML
- CSS
- REACT
---
使用 React 和 Next.js 构建博客
## 摘要
Next.js 是由 Vercel 创建和维护的基于 React 的应用程序框架。本教程将从零开始学习如何使用 Next.js 构建一个小型的博客网站。
本教程将通过创建一个简单的博客来展示 Next.js 功能,那么 Next.js 适合这样的博客的开发吗?先来了解一下一般博客都需要什么?
- WordPress 是一个内容管理系统 (CMS),它为三分之一的网站提供支持,通过在每次请求时将可编辑的数据库内容渲染到 PHP 模板中来为页面提供服务。它非常适合定期更新的内容,但性能、安全性和数据备份需要一定的自定义设置。
- 静态站点生成器 (SSG),例如 Eleventy 或 Gatsby 创建预渲染文件,无需服务器端或数据库即可快速构建静态站点,在版本控制、性能和安全性都非常出色,但构建步骤和以开发人员为中心的过程可能会减慢发布速度,尤其是在大型网站上。
Next.js 是一个基于 React 的应用程序框架,它几乎没有特定于博客功能。但是,它可以提供了一种实现机制:
1. 在可能的情况下,Next.js 生成静态内容,如 SSG,这些页面加载速度非常快,可以被搜索引擎快速收录,并且可以在任何有或没有 Javascript 的设备上阅读。
2. 在第一次加载后,Next.js 应用程序的行为类似于单页应用程序 (SPA),后续页面和代码会以渐进式下载,无需刷新整页。
3. Next.js 为每个请求提供服务器端渲染 (SSR),为个人用户提供实时 CMS 更新或自定义内容变得更加容易。
如果网站可能会从基本博客迭代为更复杂的网站,例如在线商店、新闻聚合服务、社交媒体平台等,可以考虑使用 Next.js。

内容的模板以 --- 来定义博客的标题、发布时间等元数据, --- 后面的为博客的正文。接下来需要安装解析内容的依赖,包括:front-matterremarkremark-html,执行一下命令:

npm install front-matter remark remark-html --save

要读取和解析 Markdown 文件,需要添加相关逻辑,代码所在文件 libs/posts-md.js

import promises as fsp from "fs";
import path from "path";
import fm from "front-matter";
import remark from "remark";
import remarkhtml from "remark-html";
import * as dateformat from "./dateformat";
const fileExt = "md";
// 获取文件夹相对路径
function absPath(dir)
return path.isAbsolute(dir) ? dir : path.resolve(process.cwd(), dir);
/**
* 获取文件夹中 Markdown 文件名列表,以数组形式返回
* @param * dir
* @returns
*/
export async function getFileIds(dir = "./")
const loc = absPath(dir);
const files = await fsp.readdir(loc);
return files
.filter((fn) => path.extname(fn) === `.$fileExt`)
.map((fn) => path.basename(fn, path.extname(fn)));
/**
* 获取单个 Markdown 文件的内容
* @param * dir
* @param * id
* @returns
*/
export async function getFileData(dir = "./", id)
const file = path.join(absPath(dir), `$id.$fileExt`),
stat = await fsp.stat(file),
data = await fsp.readFile(file, "utf8"),
matter = fm(data),
html = (await remark().use(remarkhtml).process(matter.body)).toString();
// 日期格式化
const date = matter.attributes.date || stat.ctime;
matter.attributes.date = date.toUTCString();
matter.attributes.dateYMD = dateformat.ymd(date);
matter.attributes.dateFriendly = dateformat.friendly(date);
// 计数
const roundTo = 10,
readPerMin = 200,
numFormat = new Intl.NumberFormat("en"),
count = matter.body
.replace(/\\W/g, " ")
.replace(/\\s+/g, " ")
.split(" ").length,
words = Math.ceil(count / roundTo) * roundTo,
mins = Math.ceil(count / readPerMin);
matter.attributes.wordcount = `$numFormat.format(
words
) words, $numFormat.format(mins)-minute read`;
return
id,
html,
...matter.attributes,
;

以上代码涉及日期格式化代码,文件路径 libs/dateformat.js

// 时间格式化
const toMOnth= new Intl.DateTimeFormat("en", month: "long" );
// 格式化为 YYYY-MM-DD
export function ymd(date)
return date instanceof Date
? `$date.getUTCFullYear()-$String(date.getUTCMonth() + 1).padStart(
2,
"0"
)-$String(date.getUTCDate()).padStart(2, "0")`
: "";
// 格式化为 DD MMMM, YYYY
export function friendly(date)
return date instanceof Date
? `$date.getUTCDate() $toMonth.format(
date
), $date.getUTCFullYear()`
: "";

Next.js 使用包含在 [ id ] 中的标识符的文件名来识别动态(生成)路由。创建一个名为 pages/articles/[id].js 的文件:Next.js 将使用 id 作为参数在 /articles/article-01 等路由处生成页面,即博客的详情页路由。

pages/articles/[id].js 中定义函数 getStaticPaths,该函数返回构建时要呈现的路径信息。

/**
* 获取博客路径信息
* @returns [ params: id: article-01 ]
*/
export async function getStaticPaths()
const paths = (await getFileIds(postsDir)).map((id) =>
return params: id ;
);
console.log(paths);
return
paths,
fallback: false,
;

接下来创建函数 getStaticProps,函数在构建时获取特定 ID 的数据以进行静态生成。它在 params 对象中传递了一个 id 属性,调用 libs/posts-md.js 中的 getFileData() 函数解析 Markdown 文件。

/**
* 解析路由获取详细内容
* @param * param0
* @returns
*/
export async function getStaticProps( params )
return
props:
postData: await getFileData(postsDir, params.id),
,
;

pages/articles/[id].js 除了解析博客内容外,还需将内容导出为一个 React 组件,组件将 postData 渲染到前面创建的模板中:

export default function Article( postData )
// 解析markdown内容
const html = `
$postData.title


$postData.wordcount


$postData.html
`;
return (







);

创建博客列表页

创建文件 pages/articles/index.js ,这个页面需要实现的功能是解析博客列表,并返回为一个 React 组件。在实现这个页面功能之前,先来创建一个链接组件 Pagelink

Pagelink 组件实现博客列表中单篇博客的布局,创建文件 components/pagelink.js ,代码如下:

import Link from "next/link";
export default function Pagelink(props)
const link = `/$props.postsdir/$props.id`;
return (




props.title



发布时间:


props.description



);

完成单个博客布局后,来看看博客列表页,代码如下:

import getAllFiles from "../../libs/posts-md";
import Layout from "../../components/layout";
import Pagelink from "../../components/pagelink";
import Head from "next/head";
const postsDir = "articles";
export default function ArticleIndex( postData )
return (



name="description"
cOntent="A list of articles published on this site."
/>

博客列表



);
/**
* 获取所有文章文章的数组
* @returns
*/
export async function getStaticProps()
return
props:
postData: await getAllFiles(postsDir),
,
;

创建导航

一个完整的博客站点,需要一个导航菜单,方便内容切换。接下来创建一个导航组件,创建文件 components/navs.js ,导出一个 组件,代码如下:

import useRouter from "next/router";
import Link from "next/link";
// menu name and link
const menu = [
text: "网站首页", link: "/" ,
text: "关于我们", link: "/about" ,
text: "博客列表", link: "/articles" ,
];
export default function Navs()
const router = useRouter(),
currentPage = router.pathname;
return (


);
function NavItem( text, link, currentpage )
if (link === currentpage)
return (

  • text

  • );
    else
    return (


  • text


  • );

    下面将 Navs 组件加入到组件 Header 中,代码如下:

    import Link from "next/link";
    import Navs from "./navs"; // 导航菜单
    export default function Header( title )
    const headerImg = "/images/" + (title || "cover.png");
    return (




    xmlns="http://www.w3.org/2000/svg"
    viewBox="0 0 20 20"

    >


    Next.js 博客








    );

    到此一个简单的博客站点功能已经实现。


    添加样式

    Next.js 提供了一系列样式选项,包括 Sass、Less、PostCSS、Styled JSX、CSS 模块和普通的CSS。 Sass 易于使用,因为不需要任何配置,按照依赖:

    npm install sass --save

    根目录下创建文件夹 styles ,所有的样式文件都放在这个文件夹下。样式的入口未见为 master.scss

    然后在文件夹 pages 下创建文件 _app.js ,将样式文件导入,完整代码如下:

    import "../styles/master.scss";
    export default function App( Component, pageProps )
    return ;

    最终效果如下:


    推荐阅读
    • scrcpy通过adb调试的方式来将手机屏幕投到电脑上,并可以通过电脑控制您的Android设备。它可以通过USB连接,也可以通过Wifi连接(类似于隔空投屏),而且不需要任何ro ... [详细]
    • RN即ReactNative基于React框架针对移动端的跨平台框架,在学习RN前建议最好熟悉下html,css,js,当然如果比较急,那就直接上手吧,毕竟用学习前面基础的时间,R ... [详细]
    • 认识Vue关于Vue的描述有不少,不外乎都会拿来与Angular和React对比,同样头顶MVVM双向数据驱动设计模式光环的Angular自然被对比的最多,但到目前为止,Angul ... [详细]
    • 知识图谱——机器大脑中的知识库
      本文介绍了知识图谱在机器大脑中的应用,以及搜索引擎在知识图谱方面的发展。以谷歌知识图谱为例,说明了知识图谱的智能化特点。通过搜索引擎用户可以获取更加智能化的答案,如搜索关键词"Marie Curie",会得到居里夫人的详细信息以及与之相关的历史人物。知识图谱的出现引起了搜索引擎行业的变革,不仅美国的微软必应,中国的百度、搜狗等搜索引擎公司也纷纷推出了自己的知识图谱。 ... [详细]
    • React基础篇一 - JSX语法扩展与使用
      本文介绍了React基础篇一中的JSX语法扩展与使用。JSX是一种JavaScript的语法扩展,用于描述React中的用户界面。文章详细介绍了在JSX中使用表达式的方法,并给出了一个示例代码。最后,提到了JSX在编译后会被转化为普通的JavaScript对象。 ... [详细]
    • Vue基础一、什么是Vue1.1概念Vue(读音vjuː,类似于view)是一套用于构建用户界面的渐进式JavaScript框架,与其它大型框架不 ... [详细]
    • 其实之前也有下载过完整的android源码,但是从来没有对这个做过一些总结,在加上最近需要经常去看,索性就在从新下载,编译一下,其实这些东西官网上面都有。http:sou ... [详细]
    • 详解react组件通讯方式(多种)
      这篇文章主要介绍了详解react组件通讯方式,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着 ... [详细]
    • macOS命令行创建Android模拟器
      macOS下不安装AndroidStudio使用VSCode来开发Flutter应用使用命令行创建和管理Android模拟器设备avdmanageravdmanager 是一种命令 ... [详细]
    • React 小白初入门
      推荐学习:React官方文档:https:react.docschina.orgReact菜鸟教程:https:www.runoob.c ... [详细]
    • 安卓及谷歌官网不容易上,在此整理好下载地址,这样就可以直接用迅雷下载了。Eclipse最新Mars版Eclipse(暂时还没被墙)Mac版:http:www.eclipse.org ... [详细]
    • 1、DashAPI文档Dash是一个API文档浏览器,使用户可以使用离线功能即时搜索无数API。程序员使用Dash可访问iOS,MacOS, ... [详细]
    • ReactJSUIAnt设计空组件原文:https://w ... [详细]
    • 前言作为一个移动端初学者、爱好者,能使用前端技术开发原生游戏一直是一件渴望而不可及的事情,暂且不说游戏逻辑的复杂度,算法的健壮性ÿ ... [详细]
    • steam,2,7,2,已经,发布 ... [详细]
    author-avatar
    丶Olrickx
    这个家伙很懒,什么也没留下!
    PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
    Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有